#include "packet_base.h"

#include <arpa/inet.h>

#include <cstring>
#include <string>

#include "common.h"
#include "log.h"

PacketBase::PacketBase(){
    buffer_ = new char[common::PROTO_BUFFER_LEN];
    Reset();
}

PacketBase::~PacketBase(){
    if(buffer_){
        delete buffer_;
        buffer_ = nullptr;
    }
}

void PacketBase::Reset(){
    buffer_size_ = common::PROTO_HEADER_LEN;
    buffer_pos_ = common::PROTO_HEADER_LEN;
    memset(buffer_, 0, common::PROTO_BUFFER_LEN);
}

void PacketBase::ResetPos(){
    buffer_pos_ = common::PROTO_HEADER_LEN;
}

void PacketBase::Copy(const void *buf, uint32_t len){
    if(buf == nullptr || len > common::PROTO_BUFFER_LEN){
        LOG_ERR("Copy超过buffer长度, len:{}", len);
        return;
    }

    Reset();
    memcpy(buffer_, buf, len);
    buffer_size_ = len;
}

void PacketBase::CopyHeader(uint32_t len, uint32_t cmd){
    WriteHeader(reinterpret_cast<char*>(&cmd), sizeof(uint16_t), common::PROTO_HEADER_CMD_INDEX);
    WriteHeader(reinterpret_cast<char*>(&len), sizeof(uint16_t), common::PROTO_HEADER_SIZE_INDEX);
    buffer_size_ = len;
}

void PacketBase::CopyBody(const char* body, uint32_t len){
    Write(body, len);
    buffer_pos_ = common::PROTO_HEADER_LEN;
    buffer_size_ = len;
}

void PacketBase::Begin(uint16_t cmd){
    Reset();
    cmd = htons(cmd);
    WriteHeader(reinterpret_cast<char*>(&cmd), sizeof(uint16_t), common::PROTO_HEADER_CMD_INDEX);
}

void PacketBase::End(){
    uint16_t body_size = buffer_size_ - common::PROTO_HEAD_CMD_LEN;
    body_size = htons(body_size);
    WriteHeader(reinterpret_cast<char*>(&body_size), sizeof(uint16_t), common::PROTO_HEADER_SIZE_INDEX);
}

void PacketBase::Write(const char* c, uint32_t len){
    if(buffer_pos_ + len > common::PROTO_BUFFER_LEN){
        LOG_ERR("超过buffer长度, buffer_pos_:{}, len:{}", buffer_pos_, len);
        return;
    }

    memcpy(buffer_ + buffer_pos_, c, len);
    buffer_pos_ += len;
    buffer_size_ += len;
}

void PacketBase::WriteHeader(char* c, uint32_t len, uint32_t pos){
    if(pos + len > common::PROTO_BUFFER_LEN){
        LOG_ERR("超过buffer长度, pos:{}, len:{}", pos, len);
        return;
    }

    memcpy(buffer_ + pos, c, len);
}


uint16_t PacketBase::GetCmd(){
    uint16_t cmd;
    ReadHeader(reinterpret_cast<char*>(&cmd), sizeof(uint16_t), common::PROTO_HEADER_CMD_INDEX);
    return ntohs(cmd);
}

uint16_t PacketBase::GetBodySize(){
    uint16_t body_size;
    ReadHeader(reinterpret_cast<char*>(&body_size), sizeof(uint16_t), common::PROTO_HEADER_SIZE_INDEX);
    return ntohs(body_size);
}

void PacketBase::ReadHeader(char* c, uint32_t len, uint32_t pos){
    if(pos + len > common::PROTO_BUFFER_LEN){
        LOG_ERR("超过buffer长度, pos:{}, len:{}", pos, len);
        return;
    }

    memcpy(c, buffer_ + pos, len);
}

void PacketBase::Read(char* c, uint32_t len, uint32_t pos){
    if(pos + len > common::PROTO_BUFFER_LEN){
        LOG_ERR("超过buffer长度, pos:{}, len:{}", pos, len);
        return;
    }

    memcpy(c, buffer_ + pos, len);
}

void PacketBase::Read(char* c, uint32_t len){
    if(buffer_pos_ + len > common::PROTO_BUFFER_LEN){
        LOG_ERR("超过buffer长度, buffer_pos_:{}, len:{}", buffer_pos_, len);
        return;
    }

    memcpy(c, buffer_ + buffer_pos_, len);
    buffer_pos_ += len;
}

void PacketBase::WriteInt16(int16_t val){
    val = htons(val);
    Write(reinterpret_cast<char*>(&val), sizeof(int16_t));
}

void PacketBase::WriteString(const std::string& str){
    uint16_t str_len = str.size();
    WriteInt16(str_len);
    Write(str.data(), str_len);
}

int16_t PacketBase::ReadInt16(){
    int16_t val;
    Read(reinterpret_cast<char*>(&val), sizeof(int16_t));
    return ntohs(val);
}

std::string PacketBase::ReadString(){
    int16_t str_len = ReadInt16();
    char c[str_len];
    Read(c, str_len);
    return std::move(std::string(c));
}

void PacketBase::WriteZero(){
    if(buffer_pos_ + 1 > common::PROTO_BUFFER_LEN){
        LOG_ERR("超过buffer长度, buffer_pos_:{}", buffer_pos_);
        return;
    }

    memset(buffer_ + buffer_size_, '\0', sizeof(char));
    buffer_size_++;
}